#include "adapter_controller.h"

namespace Controller
{
    AdaptorController::AdaptorController(std::shared_ptr<httplib::Server> &server, std::shared_ptr<Tshark::TsharkManager> &manager)
        : BaseController(server, manager)
    {
    }

    void AdaptorController::getWorkStatus(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            Tshark::WorkStatus status = m_tsharkManager->getWorkStatus();
            Json::Value data;
            data["workStatus"] = static_cast<int>(status);
            sendResponJson(resp, data);
        }
        catch (std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::startCapture(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            if (req.body.empty())
            {
                this->sendErrorResponse(resp, ERROR_PARAMETER_WRONG);
                return;
            }
            // 检查状态
            if (m_tsharkManager->getWorkStatus() != Tshark::WorkStatus::STATUS_IDLE)
            {
                this->sendErrorResponse(resp, ERROR_STATUS_WRONG);
                return;
            }
            // 解析request的json文件,检查request的参数
            Json::CharReaderBuilder readerBuilder;
            std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
            std::string errMsg;
            Json::Value reqBodyJson;
            if (!reader->parse(req.body.c_str(), req.body.c_str() + req.body.size(), &reqBodyJson, &errMsg))
            {
                LOG_F(ERROR, "%s parse to json failed!", req.body.c_str());
                this->sendErrorResponse(resp, ERROR_PARAMETER_WRONG);
                return;
            }
            if (!reqBodyJson.isMember("adapterName") || !reqBodyJson["adapterName"].isString())
            {
                LOG_F(ERROR, "%s parse to json failed!", req.body.c_str());
                this->sendErrorResponse(resp, ERROR_PARAMETER_WRONG);
                return;
            }
            std::string adapterName = reqBodyJson["adapterName"].asString();
            if (this->m_tsharkManager->startCapture(adapterName))
            {
                this->m_tsharkManager->setWorkStatus(Tshark::WorkStatus::STATUS_CAPTURING);
                this->sendSuccessResponse(resp);
            }
            else
            {
                this->sendErrorResponse(resp, ERROR_TSHARK_WRONG);
            }
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::stopCapture(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            if (m_tsharkManager->getWorkStatus() == Tshark::WorkStatus::STATUS_CAPTURING)
            {
                m_tsharkManager->stopCapture();
                this->m_tsharkManager->setWorkStatus(Tshark::WorkStatus::STATUS_IDLE);
                this->sendSuccessResponse(resp);
            }
            else
            {
                this->sendErrorResponse(resp, ERROR_STATUS_WRONG);
            }
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::startMonitorAdaptersFlowTrend(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            if (m_tsharkManager->getWorkStatus() == Tshark::WorkStatus::STATUS_IDLE)
            {
                m_tsharkManager->startMonitorAdaptersFlowTrend();
                m_tsharkManager->setWorkStatus(Tshark::WorkStatus::STATUS_MONITORING);
                this->sendSuccessResponse(resp);
            }
            else if (m_tsharkManager->getWorkStatus() == Tshark::WorkStatus::STATUS_MONITORING)
            {
                m_tsharkManager->setWorkStatus(Tshark::WorkStatus::STATUS_MONITORING);
                this->sendSuccessResponse(resp);
            }
            else
            {
                this->sendErrorResponse(resp, ERROR_STATUS_WRONG);
            }
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::stopMonitorAdaptersFlowTrend(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            if (m_tsharkManager->getWorkStatus() == Tshark::WorkStatus::STATUS_MONITORING)
            {
                this->m_tsharkManager->stopMonitorAdaptersFlowTrend();
                m_tsharkManager->setWorkStatus(Tshark::WorkStatus::STATUS_IDLE);
                this->sendSuccessResponse(resp);
            }
            else
            {
                this->sendErrorResponse(resp, ERROR_STATUS_WRONG);
            }
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::getAdaptersFlowTrendData(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            if (m_tsharkManager->getWorkStatus() != Tshark::WorkStatus::STATUS_IDLE)
            {
                this->sendErrorResponse(resp, ERROR_STATUS_WRONG);
                return;
            }
            std::map<std::string, std::map<long, long>> flowTrendMap;
            m_tsharkManager->getAdapterFlowTrendData(flowTrendMap);
            Json::Value flowTrendJson;
            flowTrendJson["code"] = ERROR_SUCCESS;
            flowTrendJson["msg"] = Tshark::TsharkError::getErrorMsg(ERROR_SUCCESS);
            // 将网卡流量数据转换为json
            Json::Value data;
            for (auto &adapterFlowTrend : flowTrendMap)
            {
                Json::Value adapterJson;
                for (auto &datePair : adapterFlowTrend.second)
                {
                    Json::Value row;
                    row["time"] = datePair.first;
                    row["bytes"] = datePair.second;
                    adapterJson.append(row);
                }
                data[adapterFlowTrend.first] = adapterJson;
            }
            flowTrendJson["data"] = data;
            Json::StreamWriterBuilder writerBuilder;
            std::string flowTrendStr = Json::writeString(writerBuilder, flowTrendJson);
            resp.set_content(flowTrendStr.c_str(), "application/json");
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::getAdaptersName(const httplib::Request &req, httplib::Response &resp)
    {
        try
        {
            auto adaptersResult = m_tsharkManager->getNetworkAdapter();
            if (!adaptersResult)
            {
                this->sendErrorResponse(resp, ERROR_TSHARK_WRONG);
                return;
            }
            std::vector<Tshark::DataType::AdapterInfo> adapters = adaptersResult.result;
            Json::Value data;
            for (auto &adapter : adapters)
            {
                data.append(adapter.toJson());
            }
            this->sendResponJson(resp, data);
        }
        catch (const std::exception &e)
        {
            this->sendErrorResponse(resp, ERROR_INTERNAL_WRONG);
        }
    }

    void AdaptorController::registerRoute()
    {
        m_server->Post("/api/getWorkStatus", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->getWorkStatus(req, resp); });
        m_server->Post("/api/startCapture", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->startCapture(req, resp); });
        m_server->Post("/api/stopCapture", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->stopCapture(req, resp); });
        m_server->Post("/api/startMonitorAdaptersFlowTrend", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->startMonitorAdaptersFlowTrend(req, resp); });
        m_server->Post("/api/stopMonitorAdaptersFlowTrend", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->stopMonitorAdaptersFlowTrend(req, resp); });
        m_server->Post("/api/getAdaptersFlowTrendData", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->getAdaptersFlowTrendData(req, resp); });
        m_server->Post("/api/getAdaptersName", [&](const httplib::Request &req, httplib::Response &resp)
                       { this->getAdaptersName(req, resp); });
    }
}